package com.example.yx1.demo35;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.WebApplicationType;
import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.GenericApplicationContext;

import java.lang.reflect.Method;

@Configuration
public class A35 {
    public static void main(String[] args) throws Exception{
        System.out.println("1.获取 Bean Definition 源");
        SpringApplication spring = new SpringApplication(A35.class);

        System.out.println("2.推断应用类型");
        Method deduce = WebApplicationType.class.getDeclaredMethod("deduceFromClasspath");
        deduce.setAccessible(true);
        System.out.println("应用类型为: " + deduce.invoke(null));

        System.out.println("3.ApplicationContext 初始化器");
        spring.addInitializers(new ApplicationContextInitializer<ConfigurableApplicationContext>() {
            @Override
            public void initialize(ConfigurableApplicationContext applicationContext) {
                GenericApplicationContext context;
                if (applicationContext instanceof GenericApplicationContext) {
                    context = (GenericApplicationContext) applicationContext;
                    context.registerBean("bean3",Bean3.class);
                }
            }
        });

        System.out.println("4.监听器与事件");
        spring.addListeners(new ApplicationListener<ApplicationEvent>() {
            @Override
            public void onApplicationEvent(ApplicationEvent event) {
                System.out.println("事件为: " + event.getClass());
            }
        });

        System.out.println("5.主类推断");
        Method deduceMainApplicationClass = SpringApplication.class.getDeclaredMethod("deduceMainApplicationClass");
        deduceMainApplicationClass.setAccessible(true);
        System.out.println("主类是: " + deduceMainApplicationClass.invoke(spring));

        ConfigurableApplicationContext context = spring.run(args);
        //创建 ApplicationContext
        //调用初始化器 对 ApplicationContext 做扩展
        //ApplicationContext.refresh
        for (String name : context.getBeanDefinitionNames()) {

            System.out.println("名字: " + name + "来源: " +context.getBeanFactory().getBeanDefinition(name).getResourceDescription());
        }

        context.close();
    }
    static class Bean1 {}
    static class Bean2 {}
    static class Bean3 {}

    @Bean
    public Bean2 bean2 () {return new Bean2();}

    @Bean
    public TomcatServletWebServerFactory tomcatServletWebServerFactory() {return new TomcatServletWebServerFactory();}
}
